package org.finesys.chat.core.base.embedding.filter.compairson;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;

import org.finesys.chat.core.base.document.Metadata;
import org.finesys.chat.core.base.embedding.filter.Filter;
import org.finesys.common.core.util.ValidationUtil;

public class NotInFilter implements Filter {

    private String key;
    private Collection<?> comparisonValues;

    public NotInFilter(String key, Collection<?> comparisonValues) {
        this.key = ValidationUtil.ensureNotBlank(key, "key");
        Set<?> copy = new HashSet<>(ValidationUtil.ensureNotEmpty(comparisonValues, "comparisonValues with key '" + key + "'"));
        comparisonValues.forEach((value) -> {
            ValidationUtil.ensureNotNull(value, "comparisonValue with key '" + key + "'");
        });
        this.comparisonValues = Collections.unmodifiableSet(copy);
    }

    public String getKey() {
        return key;
    }

    public Collection<?> getComparisonValues() {
        return comparisonValues;
    }

    @Override
    public boolean test(Object object) {
        if (object instanceof Metadata) {
            Metadata metadata = (Metadata) object;
            if (!metadata.containsKey(this.key)) {
                return false;
            }
            Object actualValue = metadata.get(this.key);
            TypeChecker.ensureTypesAreCompatible(actualValue, this.comparisonValues, this.key);
            if (this.comparisonValues.iterator().next() instanceof Number) {
                return !NumberComparator.containsAsBigDecimals(actualValue, this.comparisonValues);
            } else if (this.comparisonValues.iterator().next() instanceof UUID) {
                return !UUIDComparator.containsAsUUID(actualValue, this.comparisonValues);
            } else {
                return !this.comparisonValues.contains(actualValue);
            }
        }
        return false;
    }

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (object == null || getClass() != object.getClass()) return false;
        NotInFilter that = (NotInFilter) object;
        return Objects.equals(key, that.key) && Objects.equals(comparisonValues, that.comparisonValues);
    }

    @Override
    public int hashCode() {
        return Objects.hash(key, comparisonValues);
    }

    @Override
    public String toString() {
        return "NotInFilter{" +
                "key='" + key + '\'' +
                ", comparisonValues=" + comparisonValues +
                '}';
    }
}
